#pragma once

#include <QObject>
#include <QUdpSocket>
#include <QHostAddress>
#include <QHostInfo>
#include <QByteArray>
#include <QString>
#include <QList>
#include <QNetworkInterface>

#include <QDebug>

class DiscoverServer : public QObject
{
	Q_OBJECT

public:
	explicit DiscoverServer(QObject* parent = nullptr) : 
		QObject(parent),
		m_socket(new QUdpSocket(this))
	{
	}

	~DiscoverServer() = default;

	void start()
	{
		m_socket->bind(QHostAddress::AnyIPv4, 11411);
		connect(m_socket, &QUdpSocket::readyRead, this, &DiscoverServer::readyRead);
	}

	void stop()
	{
		disconnect(m_socket);
		m_socket->close();
	}

private:
	void processPacket(const QString& msg, const QHostAddress& host, quint16 port)
	{
		// check for discovery request header
		if(msg == "DISCOVER_REQUEST")
		{
			// build response text
			QString response;
			response.append("DISCOVER_RESPONSE\n")
					.append(getIpAddress())
					.append("\n")
					.append(QString::number(11412));

			QByteArray datagram;
			datagram.append(response);

			m_socket->writeDatagram(datagram, host, port);
		}
	}

	QString getIpAddress() const
	{
		auto addresses = QNetworkInterface::allAddresses();

		for (auto iter = addresses.begin(); iter != addresses.end(); ++iter)
		{
			if (iter->protocol() == QAbstractSocket::IPv4Protocol && !iter->isLoopback())
			{
				return iter->toString();
			}
		}

		return QString();
	}

public slots:
	void readyRead()
	{
		// process recieve packets

		while (m_socket->hasPendingDatagrams())
		{
			QByteArray buffer;
			buffer.resize(m_socket->pendingDatagramSize());

			QHostAddress sender_addr;
			quint16      sender_port;

			m_socket->readDatagram(buffer.data(), buffer.size(), &sender_addr, &sender_port);

			processPacket(QString(buffer), sender_addr, sender_port);
		}
	}

private:
	QUdpSocket* m_socket{ nullptr };
};
